#include "CShaderManager.h"
#include "CRenderDriverD3D11.h"
#include "ILDXException.h"

ldx::render::CShaderManager::CShaderManager(CRenderDriverD3D11 * driver)
	:Driver(driver), ShaderCoache(driver)
{

}

ldx::render::CShaderManager::~CShaderManager()
{
	clearPrograms();
}

ldx::render::CProgramVPS * ldx::render::CShaderManager::addProgramVPS(std::string progName, mt::wchar * vsFile, char * vsPort, mt::uint vslayercount, D3D11_INPUT_ELEMENT_DESC* descs, mt::wchar * psFile, char * psPort)
{
	SShaderMid vsmid,psmid;
	if (0 != ShaderCoache.addShader(vsFile, vsPort, EST_VERTEXSHADER, vsmid,vslayercount,descs))
	{
		throw os::ILDXException(L"CShaderManager::addProgramVPS vs shader add failed.");
		return nullptr;
	}
	if (0 != ShaderCoache.addShader(psFile, psPort, EST_PIXELSHADER, psmid))
	{
		throw os::ILDXException(L"CShaderManager::addProgramVPS ps shader add failed.");
		return nullptr;
	}

	CProgramVPS* vps = new CProgramVPS(Driver->getDeviceMap());
	vps->set(vsmid);
	vps->set(psmid);
	insertProgram(progName, vps);
	return vps;
}

bool ldx::render::CShaderManager::isProgramExist(std::string & name)
{
	std::unordered_map<std::string, IProgram*>::iterator it = HashMapOfPrograms.find(name);
	if (it != HashMapOfPrograms.end())
	{
		return true;
	}
	return false;
}

ldx::render::IProgram * ldx::render::CShaderManager::getProgram(const std::string & proName) const
{
	std::unordered_map<std::string, IProgram*>::const_iterator it = HashMapOfPrograms.find(proName);
	if (it != HashMapOfPrograms.end())
	{
		return (*it).second;
	}
	return nullptr;
}

int ldx::render::CShaderManager::insertProgram(std::string & name, IProgram *prog)
{
	if (isProgramExist(name))
	{
		return 1;
	}
	HashMapOfPrograms.insert(std::pair<std::string,IProgram*>(name,prog));
	return 0;
}

void ldx::render::CShaderManager::clearPrograms()
{
	std::unordered_map<std::string, IProgram*>::iterator it;
	for (it = HashMapOfPrograms.begin(); it != HashMapOfPrograms.end(); ++it)
	{
		delete (*it).second;
	}
	HashMapOfPrograms.clear();
}
